#pragma once

#include <base.h>

#define IPI_FIXED 0
#define IPI_SMI (0b010)
#define IPI_NMI (0b100)
#define IPI_INIT (0b101)
#define IPI_STARTUP (0b110)
#define IPI_ASSERT BIT(6)
#define IPI_LEVEL_TRIGGER BIT(7)

#define APIC_TIMER_FREQ (1000)	//  Hz
#define APIC_TIMER_INTERVAL (1000000000 / APIC_TIMER_FREQ)

#define LVT_IDX_TIMER 0
#define LVT_IDX_THERMAL 1
#define LVT_IDX_PERF 2
#define LVT_IDX_LINT0 3
#define LVT_IDX_LINT1 4
#define LVT_IDX_ERROR 5

void lapic_init();
uint32_t lapic_ap_init();

void lapic_write32(uint32_t reg, uint32_t val);
void lapic_write64(uint32_t reg, uint64_t val);
uint32_t lapic_read32(uint32_t reg);
uint64_t lapic_read64(uint32_t reg);

uint32_t lapic_read_lvt(uint32_t index);
void lapic_write_lvt(uint32_t index, uint32_t val);
void lapic_mask_lvt(uint32_t index, bool enable);

void lapic_send_ipi(uint32_t apic_id, uint32_t ipi_type, uint8_t vector);

uint32_t lapic_get_self_id();

void lapic_start_timer();